package asem.ast.sentencias;

import genc.GenC;

import java.util.HashMap;
import java.util.LinkedList;

import ppal.ErroresSemanticos;
import asem.TablaSimbolos;
import asem.excepciones.ExcepcionFaltaRetorno;
import asem.excepciones.ExcepcionSemantica;
import asem.tablaSimbolos.Constructor;
import asem.tablaSimbolos.Metodo;
import asem.tablaSimbolos.Variable;
import asem.tablaSimbolos.VariableLocal;
import asem.tablaSimbolos.tipo.TipoVoid;

public class NodoBloque extends NodoSentencia {
	protected LinkedList<NodoSentencia> conjuntoSentencias;
	protected HashMap<String, Variable> varsAccesibles;
	protected int cantVarsLocal;

	protected NodoBloque contenedor;

	public NodoBloque(LinkedList<NodoSentencia> lista) {
		conjuntoSentencias = lista;
		varsAccesibles = new HashMap<String, Variable>();
		cantVarsLocal = 0;
	}

	public NodoBloque() {
		conjuntoSentencias = null;
		varsAccesibles = new HashMap<String, Variable>();
	}

	public LinkedList<NodoSentencia> getSentencias() {
		return conjuntoSentencias;
	}

	public void addVar(String lexema, Variable var) {
		varsAccesibles.put(lexema, var);
	}

	public void addVarLocal(String lexema, VariableLocal var) {
		var.setOffset(getCantVars());
		varsAccesibles.put(lexema, var);
		cantVarsLocal++;
	}

	public HashMap<String, Variable> getVars() {
		return varsAccesibles;
	}

	public Variable getVar(String lexema) {
		return varsAccesibles.get(lexema);
	}

	public int getCantVars() {
		int retu = cantVarsLocal;

		if (contenedor != null)
			retu = retu + contenedor.getCantVars();

		return retu;
	}

	public boolean chequeoSentencias(NodoBloque contenedor) {
		this.contenedor = contenedor;

		boolean r = false;

		if (contenedor != null)
			// Estoy en un subbloque -> mis varsAccesibles son las vars
			// accesibles de mi bloque contenedor
			varsAccesibles = new HashMap<String, Variable>(contenedor.getVars());

		if (conjuntoSentencias != null)
			for (NodoSentencia sen : conjuntoSentencias) {
				try {
					r = sen.chequeoSentencias(this) || r;
				} catch (ExcepcionSemantica e) {
					ErroresSemanticos.errores.addExcepcion(e);
					// De este modo podemos detectar 1 error a nivel de
					// sentencia.
				}
			}

		Constructor aux = TablaSimbolos.tabla.metodoActual();
		if (contenedor == null && !r)
			if (aux instanceof Metodo)
				if (!aux.getRetorno().equals(TipoVoid.TIPO))
					ErroresSemanticos.errores
							.addExcepcion(new ExcepcionFaltaRetorno(aux
									.getIdentificador()));

		if (cantVarsLocal > 0)
			GenC.gen.liberarMem(Integer.toString(cantVarsLocal),
					"Desreservo lugar para variables locales del bloque -> "
							+ cantVarsLocal);

		if (contenedor == null) // estoy en el mayor bloque
			GenC.gen.terminaMetodo(aux, 0);

		return r;
	}


}
